package com.yicheng.statistics.actor.analysis

import com.yicheng.statistics.actor.SaveHtaData

import akka.actor.Actor
import akka.actor.ActorLogging
import akka.actor.ActorRef
import akka.actor.Props
import com.yicheng.statistics.common.HTADB
import com.yicheng.statistics.service.HTAService
import com.yicheng.statistics.repo.cassandra.DataInfoDB
import com.yicheng.statistics.common.TimeUtils
import scala.util.Failure
import scala.util.Success
import java.util.Date
import com.yicheng.statistics.common.RTAModel
import org.joda.time.DateTime
import com.yicheng.statistics.repo.RTAModel.VehicleTired
import com.yicheng.statistics.repo.model.Data.DataInfo
import com.carcloud.gateway.bean.data.DataVehPos
import com.carcloud.gateway.bean.data.DataVehOverall

/**
 * 疲劳驾驶统计
 */
class TriedDrive extends Actor with ActorLogging{
  
  val saveHtaDataActor:ActorRef = context.child("saveHtaData").
    getOrElse(context.actorOf(Props[SaveHtaData], "saveHtaData"))
  
  import scala.concurrent.ExecutionContext.Implicits.global
  def receive: Receive = {
    case (deviceId:String,deviceType:Int, analyseGroupId:Long) =>
      log.info("疲劳驾驶 deviceId "+deviceId)
      
      HTAService.getOneDayDataInfo(deviceType, deviceId) onComplete { 
        case Success(dataInfos) =>
          HTADB.getVehicleTiredSettings(analyseGroupId).map(s => 
            Parser(
              deviceId, 
              deviceType,
              s.headOption.get, 
              dataInfos.sortWith((d1:DataInfo, d2:DataInfo) => d1.data_time.getTime < d2.data_time.getTime)))
        case Failure(error) =>
          log.info(error.getStackTrace.toString())
      }
      
    case _ => log.info("TriedDrive")
  }
  
  /**
   * 解析疲劳驾驶
   * 1 存储数据到时间报警
   */
  def Parser(deviceId:String ,deviceType:Int, setting:RTAModel.VehicleTiredSetting , dataInfos : List[DataInfo]):Unit = {
    
    var tiredTimeState:TiredTimeState = TiredTimeState(false, true, None, None,None, None,None, None,None, None,None, 0, false)
    var mileageState : MileageState = MileageState(None, None, Some(0), None, None, None, None)
    var vehicleTired: VehicleTired = VehicleTired(
        deviceType, deviceId, None, None, None, None, 
        None, None, None, None, None, None,
        None, None, None, None, DateTime.now().toDate(), None)
    
    
    val dayTimeWarnning =  setting.timeThreshold - setting.earlyWarningThreshold//提前预警时间
    val dayWarnnigStartTime = TimeUtils.time2DateTime(setting.startTime, TimeUtils.getPreDateTime()).toDate().getTime()
    val dayWarnnigEndTime = TimeUtils.time2DateTime(setting.endTime, TimeUtils.getPreDateTime()).toDate().getTime()
    var timeThreshold = setting.timeThreshold
    
    dataInfos.foreach( di => {
      val posData: DataVehPos = di.data_vehicle.dataVehicle.get.posData.get
      val overAllData: DataVehOverall = di.data_vehicle.dataVehicle.get.overallData.get
      
      //夜间间行车
      if(TimeUtils.inTimeRang(setting.nightDriveBeginTime.get, setting.nightDriveendTime.get, di.data_time)){
        timeThreshold = setting.nightTimeThreshold.get
      }
      //日间行车
      if( TimeUtils.inTimeRang(setting.startTime, setting.endTime, di.data_time)){
        timeThreshold = setting.timeThreshold
      }
      
      if(!tiredTimeState.start) {//是否记录第一条数据
        tiredTimeState = tiredTimeState.copy(start = true, startTime = Some(di.data_time))
        mileageState = mileageState.copy(
            totalStartMileage = Some(overAllData.currentMileage),
            driveStartMileage = Some(overAllData.currentMileage))
      }else{
        
        //1如果两条数据间隔时间比较长，当大于休息时长的时候 如果报警中 消除报警 
        val restTime = TimeUtils.secondsBetweenTime(tiredTimeState.endTime.get, di.data_time)
        if( restTime > setting.effectiveRestTime){
          
          if(tiredTimeState.firestAlramFlag){//是第一次报警 记录第一次报警的开始时间是地点
            //记录统计数据的第一次报警的开始时间 开始坐标
            vehicleTired = vehicleTired.copy(
              startdatetime = tiredTimeState.startTime, 
              startlon = tiredTimeState.startLon, 
              startlat = tiredTimeState.endLat)
          }
          
          if( tiredTimeState.state ){//报警中 消除报警 计算报警总时长
            tiredTimeState = tiredTimeState.copy(
              startTime = Some(di.data_time),
              startLat = posData.latitude,
              startLon = posData.longitude,
              state = false, 
              restTotalTime = Some(tiredTimeState.restTotalTime.get + restTime),
              totalTime = Some(0) ,
              alarmTotalTime = Some( tiredTimeState.alarmTotalTime.get + TimeUtils.secondsBetweenTime(tiredTimeState.endTime.get, tiredTimeState.startTime.get)))//消除报警
              
            //报警结束 记录结束的地点时间
            vehicleTired = vehicleTired.copy(
              enddatetime = Some(di.data_time), 
              endlon = posData.longitude, 
              endlat = posData.latitude)
           
            val currentAlarmMileage = overAllData.currentMileage - mileageState.startMileage.get
            //计算报警结束的里程
            mileageState = mileageState.copy(
                driveStartMileage = Some(overAllData.currentMileage),
                startMileage = Some(overAllData.currentMileage),
                alarmTotalMileage = Some(mileageState.alarmTotalMileage.get + currentAlarmMileage))
          }else{//没有报警清理数据，开始新一论的统计  计算休息的总时长
            tiredTimeState = tiredTimeState.copy(
              startTime = Some(di.data_time),
              startLat = posData.latitude,
              startLon = posData.longitude,
              state = false, 
              restTotalTime = Some(tiredTimeState.restTotalTime.get + restTime),
              totalTime = Some(0))
            //重新开始计算行驶里程 设置行驶里程的初始值
            mileageState = mileageState.copy(
                driveStartMileage = Some(overAllData.currentMileage))
          }
        }//1如果休息时长不够继续下面的判断
        
        if( (tiredTimeState.totalTime.get > timeThreshold)
            && (mileageState.driveMileage.get > setting.minDistance) ){//如果大于时间阀值并且行驶的距离大于行驶最小距离 开始计算报警的统计
          log.info("开始计算报警 ")
          if(tiredTimeState.state){//继续计算超速的数据
            tiredTimeState = tiredTimeState.copy(
              totalTime = Some(di.data_time.getTime - tiredTimeState.startTime.get.getTime))//当前运行的时间继续增加
          }else{
            //设置对象处于报警状态
            tiredTimeState = tiredTimeState.copy(//处于报警状态
              startTime = Some(di.data_time),
              startLat = posData.latitude,
              startLon = posData.longitude,
              endTime = Some(di.data_time), 
              totalTime = Some(di.data_time.getTime - tiredTimeState.startTime.get.getTime),
              count = tiredTimeState.count + 1,
              state = true)
              
            mileageState = mileageState.copy(
              startMileage = Some(overAllData.currentMileage),
              totalMileage = Some(0),
              alarmTotalMileage = Some(0))
          }
          
        }else{//没有超过时间阀值 继续增行驶时间 增加行驶里程
          tiredTimeState = tiredTimeState.copy(
            endTime = Some(di.data_time),
            endLat = posData.latitude,
            endLon = posData.longitude,
            totalTime = Some(di.data_time.getTime - tiredTimeState.startTime.get.getTime))
          
          //计算行驶里程
          mileageState = mileageState.copy(driveMileage = Some(overAllData.currentMileage - mileageState.driveStartMileage.get))
        }
        
      }
    })
    
    if(tiredTimeState.state){//全部数据解析完毕 如果处在报警中 记录最后一次的位置时间  报警次数加一 报警时间增加
      //报警结束 记录结束的地点时间
      vehicleTired = vehicleTired.copy(
        mileagethreshold = Some(0),
        timethreshold = Some(setting.timeThreshold),
        totaltime = Some(tiredTimeState.alarmTotalTime.get.toInt),
        enddatetime = tiredTimeState.endTime, 
        endlon = tiredTimeState.endLon, 
        endlat = tiredTimeState.endLat,
        startmileage = mileageState.startMileage,
        endmileage = mileageState.endMileage,
        totalmileage = mileageState.alarmTotalMileage,
        analysegroupsid = Some(setting.analyseGroupsID.toInt),
        analyseconditions = Some(""),
        createdatetime = DateTime.now().toDate())
    }
    //保存数据库
    saveHtaDataActor ! vehicleTired
  }
}

/**
 * 疲劳驾驶时间数据状态存储
 */
case class TiredTimeState(
    start:Boolean,//
    firestAlramFlag:Boolean,
    startTime:Option[Date],
    endTime:Option[Date],
    totalTime:Option[Long],//累计行驶时间
    restTotalTime:Option[Long],//休息总时长
    alarmTotalTime:Option[Long],//报警总时长
    startLat:Option[Double],//第一次报警开始纬度
    startLon:Option[Double],//第一次报警开始精度
    endLat:Option[Double],//最后一次报警结束纬度
    endLon:Option[Double],//最后一次报警结束精度
    count:Int,//报警次数
    state:Boolean)
    
case class MileageState(
  totalStartMileage:Option[Int],//计算一天总里程开始数据
  driveStartMileage:Option[Int],//每次行驶开始里程
  driveMileage:Option[Int],//行驶里程，每次休息完重新记录表显里程
  startMileage:Option[Int],//报警开始里程
  endMileage:Option[Int],//报警结束里程
  totalMileage:Option[Int],//行驶总里程
  alarmTotalMileage:Option[Int])//报警总里程